package com.william.jdbcplus.core.dialect.ddl;

import com.william.jdbcplus.common.entity.Entity;
import com.william.jdbcplus.common.enums.DbType;
import com.william.jdbcplus.core.dialect.ddl.table.ITable;
import com.william.jdbcplus.core.dialect.ddl.table.TableFactory;
import com.william.jdbcplus.core.dialect.ddl.util.*;
import com.william.jdbcplus.core.dialect.ddl.util.model.TableMeta;
import com.william.jdbcplus.core.dialect.ddl.util.model.TableSort;
import com.william.jdbcplus.core.dialect.ddl.util.model.TableSortSql;
import com.william.jdbcplus.core.dialect.meta.MetaUtil;
import com.william.jdbcplus.core.meta.TableFkInfo;
import com.william.jdbcplus.core.meta.TableHelperUtil;
import com.william.jdbcplus.core.meta.TableInfo;
import com.william.jdbcplus.core.toolkit.ReflectionsUtil;
import com.william.jdbcplus.core.util.JdbcExecUtil;
import com.william.jdbcplus.core.util.JdbcUtil;
import com.william.jdbcplus.core.util.datameta.DatabaseMetaInfo;
import com.william.jdbcplus.core.util.datameta.TableMetaInfo;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据库DDL操作类
 *
 * @author william
 */
@Slf4j
public class DDLUtil {

    /**
     * 检查实体表结构
     *
     * @param clazz 实体类
     * @param ds    数据源
     * @return
     */
    public static List<String> checkTable(Class<? extends Entity> clazz, DataSource ds) {
        DbType dbType = JdbcUtil.getDbType(ds);
        List<TableSortSql> createSqlList = new ArrayList<>();
        createSqlList.add(createTableSql(dbType, clazz));
        DatabaseMetaInfo dbMeta = MetaUtil.getDatabaseInfo(ds);
        List<String> existTableList = dbMeta.getTableInfoList().stream().map(e -> e.getTableName().toLowerCase()).collect(Collectors.toList());

        List<String> errList = new ArrayList<>();

        // 1 需要创建的表脚本
        List<TableSortSql> realCreateSqls = getRealCreateTableNames(createSqlList, existTableList);
        for (TableSortSql table : realCreateSqls) {
            TableInfo tableInfo = TableHelperUtil.getTableInfo(table.getClazz());
            errList.add("表 " + tableInfo.getTableName() + " 不存在");
        }

        // 2 获取需要更新的表信息
        List<TableMeta> updateMetas = getUpdateTableMetaInfos(createSqlList, dbMeta);
        for (TableMeta meta : updateMetas) {
            // 检查列是否一致
            errList.addAll(ColumnUtil.check(dbType, meta));
            // 检查主键是否一致
            errList.addAll(PkUtil.check(dbType, meta));
            // 检查唯一键
            errList.addAll(UkUtil.check(dbType, meta));
            // 检查索引
            errList.addAll(IndexUtil.check(dbType, meta));
            // 检查外键
            errList.addAll(FkUtil.check(dbType, meta));
        }

        return errList;
    }

    /**
     * 更新实体表结构
     *
     * @param clazz 实体类
     * @param ds    数据源
     * @return
     */
    public static void updateTable(Class<? extends Entity> clazz, DataSource ds) {
        DbType dbType = JdbcUtil.getDbType(ds);
        List<TableSortSql> createSqlList = new ArrayList<>();
        createSqlList.add(createTableSql(dbType, clazz));
        DatabaseMetaInfo dbMeta = MetaUtil.getDatabaseInfo(ds);
        List<String> existTableList = dbMeta.getTableInfoList().stream().map(e -> e.getTableName().toLowerCase()).collect(Collectors.toList());

        // 1 需要创建的表脚本
        List<String> realCreateSqls = getRealCreateSqlList(createSqlList, existTableList);

        // 2 获取需要更新的表信息
        List<TableMeta> updateMetaList = getUpdateTableMetaInfos(createSqlList, dbMeta);

        //执行建表脚本
        JdbcExecUtil.exec(realCreateSqls, ds);

        for (TableMeta meta : updateMetaList) {
            // 更新列
            ColumnUtil.update(dbType, meta, ds);
            // 更新主键
            PkUtil.update(dbType, meta, ds);
            // 更新唯一键
            UkUtil.update(dbType, meta, ds);
            // 更新索引
            IndexUtil.update(dbType, meta, ds);
            // 更新外键
            FkUtil.update(dbType, meta, ds);
        }
    }

    /**
     * 获取更新实体表结构脚本
     *
     * @param clazz 实体类
     * @param ds    数据源
     * @return
     */
    public static List<String> updateTableSql(Class<? extends Entity> clazz, DataSource ds) {
        DbType dbType = JdbcUtil.getDbType(ds);
        List<TableSortSql> createSqlList = new ArrayList<>();
        createSqlList.add(createTableSql(dbType, clazz));
        DatabaseMetaInfo dbMeta = MetaUtil.getDatabaseInfo(ds);
        List<String> existTableList = dbMeta.getTableInfoList().stream().map(e -> e.getTableName().toLowerCase()).collect(Collectors.toList());

        // 1 需要创建的表脚本
        List<String> realCreateSqls = getRealCreateSqlList(createSqlList, existTableList);

        // 2 获取需要更新的表信息
        List<TableMeta> updateMetaList = getUpdateTableMetaInfos(createSqlList, dbMeta);

        List<String> sqlList = new LinkedList<>();
        //先添加建表脚本
        sqlList.addAll(realCreateSqls);

        for (TableMeta meta : updateMetaList) {
            // 更新列
            sqlList.addAll(ColumnUtil.getUpdateSQL(dbType, meta));
            // 更新主键
            sqlList.addAll(PkUtil.getUpdateSQL(dbType, meta));
            // 更新唯一键
            sqlList.addAll(UkUtil.getUpdateSQL(dbType, meta));
            // 更新索引
            sqlList.addAll(IndexUtil.getUpdateSQL(dbType, meta));
            // 更新外键
            sqlList.addAll(FkUtil.getUpdateSQL(dbType, meta));
        }

        return sqlList;
    }

    /**
     * 根据实体建表
     *
     * @param clazz 实体类
     * @param ds    数据源
     */
    public static void createTable(Class<? extends Entity> clazz, DataSource ds) {
        DbType dbType = JdbcUtil.getDbType(ds);
        TableSortSql createTableSql = createTableSql(dbType, clazz);
        List<String> tableList = JdbcUtil.getTables(ds).stream().map(e -> e.toLowerCase()).collect(Collectors.toList());
        // 不存在的表，才能创建
        List<String> realCreateSqls = new LinkedList<>();
        TableInfo tableInfo = TableHelperUtil.getTableInfo(clazz);
        String tableName = tableInfo.getTableName().toLowerCase();
        if (!tableList.contains(tableName)) {
            realCreateSqls.add(createTableSql.getSql());
        } else {
            log.error("表已经存在不允许创建");
        }

        //执行脚本
        JdbcExecUtil.exec(realCreateSqls, ds);
    }

    /**
     * 清空实体对应表数据
     *
     * @param clazz 实体类
     * @param ds    数据源
     * @return
     */
    public static void deleteTable(Class<? extends Entity> clazz, DataSource ds) {
        DbType dbType = JdbcUtil.getDbType(ds);
        TableSortSql deleteSq = deleteTableSql(dbType, clazz);
        List<String> tableList = JdbcUtil.getTables(ds).stream().map(e -> e.toLowerCase()).collect(Collectors.toList());
        // 存在的表，才删除
        List<String> realDeleteSqls = new LinkedList<>();
        TableInfo tableInfo = TableHelperUtil.getTableInfo(clazz);
        String tableName = tableInfo.getTableName().toLowerCase();
        if (tableList.contains(tableName)) {
            realDeleteSqls.add(deleteSq.getSql());
        } else {
            log.error("表不存在不能清空表数据");
        }

        //执行脚本
        JdbcExecUtil.exec(realDeleteSqls, ds);
    }

    /**
     * 删除实体对应表
     *
     * @param clazz 实体类
     * @param ds    数据源
     * @return
     */
    public static void dropTable(Class<? extends Entity> clazz, DataSource ds) {
        DbType dbType = JdbcUtil.getDbType(ds);
        TableSortSql dropSql = dropTableSql(dbType, clazz);
        List<String> tableList = JdbcUtil.getTables(ds).stream().map(e -> e.toLowerCase()).collect(Collectors.toList());
        // 存在的表，才删除
        List<String> realDropSqls = new LinkedList<>();
        TableInfo tableInfo = TableHelperUtil.getTableInfo(clazz);
        String tableName = tableInfo.getTableName().toLowerCase();
        if (tableList.contains(tableName)) {
            realDropSqls.add(dropSql.getSql());
        } else {
            log.error("表不存在无需删除");
        }

        //执行脚本
        JdbcExecUtil.exec(realDropSqls, ds);
    }

    /**
     * 删除模块下存在的表数据,不存在，则不删除数据
     *
     * @param scanPackage 扫描包根目录
     * @param ds          数据源
     */
    public static void deleteDatabaseTables(String scanPackage, DataSource ds) {
        DbType dbType = JdbcUtil.getDbType(ds);
        List<TableSortSql> deleteSqlList = deleteTableSqlList(dbType, scanPackage);
        // 存在的表，才删除
        List<String> realDeleteSqls = new LinkedList<>();
        List<String> tableList = JdbcUtil.getTables(ds).stream().map(e -> e.toLowerCase()).collect(Collectors.toList());
        for (TableSortSql delete : deleteSqlList) {
            TableInfo tableInfo = TableHelperUtil.getTableInfo(delete.getClazz());
            String tableName = tableInfo.getTableName().toLowerCase();
            if (tableList.contains(tableName)) {
                realDeleteSqls.add(delete.getSql());
            }
        }

        //执行脚本
        JdbcExecUtil.exec(realDeleteSqls, ds);
    }

    /**
     * 删除模块下存在的表,不存在，则不删除
     *
     * @param scanPackage 扫描包根目录
     * @param ds          数据源
     */
    public static void dropDatabaseTables(String scanPackage, DataSource ds) {
        DbType dbType = JdbcUtil.getDbType(ds);
        List<TableSortSql> dropList = dropTableSqlList(dbType, scanPackage);
        // 存在的表，才删除
        List<String> realDropSqls = new LinkedList<>();
        List<String> tableList = JdbcUtil.getTables(ds).stream().map(e -> e.toLowerCase()).collect(Collectors.toList());
        for (TableSortSql drop : dropList) {
            TableInfo tableInfo = TableHelperUtil.getTableInfo(drop.getClazz());
            String tableName = tableInfo.getTableName().toLowerCase();
            if (tableList.contains(tableName)) {
                realDropSqls.add(drop.getSql());
            }
        }

        //执行脚本
        JdbcExecUtil.exec(realDropSqls, ds);
    }

    /**
     * 创建模块下的表，只创建不存在的表
     *
     * @param scanPackage 扫描包根目录
     * @param ds          数据源
     */
    public static void createDatabaseTables(String scanPackage, DataSource ds) {
        DbType dbType = JdbcUtil.getDbType(ds);
        List<TableSortSql> createTableList = createTableSqlList(dbType, scanPackage);
        List<String> tableList = JdbcUtil.getTables(ds).stream().map(e -> e.toLowerCase()).collect(Collectors.toList());
        // 不存在的表，才能创建
        List<String> realCreateSqls = new LinkedList<>();
        for (TableSortSql create : createTableList) {
            TableInfo tableInfo = TableHelperUtil.getTableInfo(create.getClazz());
            String tableName = tableInfo.getTableName().toLowerCase();
            if (!tableList.contains(tableName)) {
                realCreateSqls.add(create.getSql());
            }
        }

        //执行脚本
        JdbcExecUtil.exec(realCreateSqls, ds);
    }

    /**
     * 获取更新数据库的全部脚本
     * <p>
     * 如果不存在表则创建表结构，如果存在则更新表结构
     * </p>
     *
     * @param scanPackage
     * @param ds
     */
    public static List<String> updateDatabaseSqlList(String scanPackage, DataSource ds) {
        DbType dbType = JdbcUtil.getDbType(ds);
        List<TableSortSql> createSqlList = createTableSqlList(dbType, scanPackage);
        DatabaseMetaInfo dbMeta = MetaUtil.getDatabaseInfo(ds);
        List<String> existTableList = dbMeta.getTableInfoList().stream().map(e -> e.getTableName().toLowerCase()).collect(Collectors.toList());

        // 1 需要创建的表脚本
        List<String> realCreateSqls = getRealCreateSqlList(createSqlList, existTableList);

        // 2 获取需要更新的表信息
        List<TableMeta> updateMetaList = getUpdateTableMetaInfos(createSqlList, dbMeta);

        List<String> sqlList = new LinkedList<>();
        //先添加建表脚本
        sqlList.addAll(realCreateSqls);

        for (TableMeta meta : updateMetaList) {
            // 更新列
            sqlList.addAll(ColumnUtil.getUpdateSQL(dbType, meta));
            // 更新主键
            sqlList.addAll(PkUtil.getUpdateSQL(dbType, meta));
            // 更新唯一键
            sqlList.addAll(UkUtil.getUpdateSQL(dbType, meta));
            // 更新索引
            sqlList.addAll(IndexUtil.getUpdateSQL(dbType, meta));
            // 更新外键
            sqlList.addAll(FkUtil.getUpdateSQL(dbType, meta));
        }

        return sqlList;
    }

    /**
     * 检测数据库，返回数据库结构不一致的全部信息
     *
     * @param scanPackage
     * @param ds
     */
    public static List<String> checkDatabase(String scanPackage, DataSource ds) {
        DbType dbType = JdbcUtil.getDbType(ds);
        List<TableSortSql> createSqlList = createTableSqlList(dbType, scanPackage);
        DatabaseMetaInfo dbMeta = MetaUtil.getDatabaseInfo(ds);
        List<String> existTableList = dbMeta.getTableInfoList().stream().map(e -> e.getTableName().toLowerCase()).collect(Collectors.toList());

        List<String> errList = new ArrayList<>();

        // 1 需要创建的表脚本
        List<TableSortSql> realCreateSqls = getRealCreateTableNames(createSqlList, existTableList);
        for (TableSortSql table : realCreateSqls) {
            TableInfo tableInfo = TableHelperUtil.getTableInfo(table.getClazz());
            errList.add("表 " + tableInfo.getTableName() + " 不存在");
        }

        // 2 获取需要更新的表信息
        List<TableMeta> updateMetas = getUpdateTableMetaInfos(createSqlList, dbMeta);
        for (TableMeta meta : updateMetas) {
            // 检查列是否一致
            errList.addAll(ColumnUtil.check(dbType, meta));
            // 检查主键是否一致
            errList.addAll(PkUtil.check(dbType, meta));
            // 检查唯一键
            errList.addAll(UkUtil.check(dbType, meta));
            // 检查索引
            errList.addAll(IndexUtil.check(dbType, meta));
            // 检查外键
            errList.addAll(FkUtil.check(dbType, meta));
        }

        return errList;
    }


    /**
     * 更新数据库，更新全部结构，如果不存在表则创建表结果，如果存在则更新结构
     *
     * @param scanPackage
     * @param ds
     */
    public static void updateDatabase(String scanPackage, DataSource ds) {
        DbType dbType = JdbcUtil.getDbType(ds);
        List<TableSortSql> createSqlList = createTableSqlList(dbType, scanPackage);
        DatabaseMetaInfo dbMeta = MetaUtil.getDatabaseInfo(ds);
        List<String> existTableList = dbMeta.getTableInfoList().stream().map(e -> e.getTableName().toLowerCase()).collect(Collectors.toList());

        // 1 需要创建的表脚本
        List<String> realCreateSqls = getRealCreateSqlList(createSqlList, existTableList);

        // 2 获取需要更新的表信息
        List<TableMeta> updateMetaList = getUpdateTableMetaInfos(createSqlList, dbMeta);

        //执行建表脚本
        JdbcExecUtil.exec(realCreateSqls, ds);

        for (TableMeta meta : updateMetaList) {
            // 更新列
            ColumnUtil.update(dbType, meta, ds);
            // 更新主键
            PkUtil.update(dbType, meta, ds);
            // 更新唯一键
            UkUtil.update(dbType, meta, ds);
            // 更新索引
            IndexUtil.update(dbType, meta, ds);
            // 更新外键
            FkUtil.update(dbType, meta, ds);
        }
    }

    /**
     * 获取要更新的表信息
     *
     * @param createSqlList 需要创建的表信息
     * @param dbMeta        数据库信息
     */
    private static List<TableMeta> getUpdateTableMetaInfos(List<TableSortSql> createSqlList, DatabaseMetaInfo dbMeta) {
        List<TableMeta> resultList = new ArrayList<>();
        Map<String, TableMetaInfo> tableMap = dbMeta.getTableInfoList().stream().collect(Collectors.toMap(e -> e.getTableName().toLowerCase(), e -> e));
        for (TableSortSql create : createSqlList) {
            TableInfo tableInfo = TableHelperUtil.getTableInfo(create.getClazz());
            String tableName = tableInfo.getTableName().toLowerCase();
            if (tableMap.containsKey(tableName)) {
                resultList.add(new TableMeta(create.getClazz(), tableMap.get(tableName), tableInfo));
            }
        }

        return resultList;
    }

    /**
     * 根据创建表脚本和已经存在的表获取要创建的真实表脚本
     *
     * @param createSqlList  需要创建的表脚本
     * @param existTableList 数据库中已经存在的表
     */
    private static List<String> getRealCreateSqlList(List<TableSortSql> createSqlList, List<String> existTableList) {
        // 不存在的表，才能创建
        List<String> sqlList = new LinkedList<>();
        for (TableSortSql create : createSqlList) {
            TableInfo tableInfo = TableHelperUtil.getTableInfo(create.getClazz());
            String tableName = tableInfo.getTableName().toLowerCase();
            if (!existTableList.contains(tableName)) {
                sqlList.add(create.getSql());
            }
        }

        return sqlList;
    }

    /**
     * 获取需要创建的表
     *
     * @param createSqlList  需要创建的表脚本
     * @param existTableList 数据库中已经存在的表
     */
    private static List<TableSortSql> getRealCreateTableNames(List<TableSortSql> createSqlList, List<String> existTableList) {
        // 不存在的表，才能创建
        List<TableSortSql> realCreateTables = new LinkedList<>();
        for (TableSortSql create : createSqlList) {
            TableInfo tableInfo = TableHelperUtil.getTableInfo(create.getClazz());
            String tableName = tableInfo.getTableName().toLowerCase();
            if (!existTableList.contains(tableName)) {
                realCreateTables.add(create);
            }
        }

        return realCreateTables;
    }

    /**
     * 获取初始化顺序
     *
     * @param scanPackage
     * @return
     */
    public static List<Class<? extends Entity>> getSortClassList(String scanPackage) {
        Set<Class<? extends Entity>> classSetAll = ReflectionsUtil.getSubClassSet(Entity.class, scanPackage);
        List<Class<? extends Entity>> entityList = getSortEntityList(classSetAll);
        return entityList;
    }

    /**
     * 按顺序清空所有表脚本列表
     *
     * @param dbType
     * @param scanPackage
     * @return
     */
    private static List<TableSortSql> deleteTableSqlList(DbType dbType, String scanPackage) {
        List<TableSortSql> sqlList = new LinkedList<>();
        Set<Class<? extends Entity>> classSetAll = ReflectionsUtil.getSubClassSet(Entity.class, scanPackage);
        List<Class<? extends Entity>> entityList = getSortEntityList(classSetAll);
        // 反转list，必须反转，创建顺序与删除顺序正好相反
        Collections.reverse(entityList);
        ITable iTable = TableFactory.getInstance(dbType);
        for (Class<? extends Entity> entityClass : entityList) {
            String sql = iTable.delete(entityClass);
            sqlList.add(new TableSortSql(sql, entityClass));
        }
        return sqlList;
    }

    /**
     * 删除表脚本
     *
     * @param dbType
     * @param clazz
     * @return
     */
    private static TableSortSql deleteTableSql(DbType dbType, Class<? extends Entity> clazz) {
        ITable iTable = TableFactory.getInstance(dbType);
        String sql = iTable.delete(clazz);
        TableSortSql result = new TableSortSql(sql, clazz);
        return result;
    }

    /**
     * 按顺序删除所有表脚本列表
     *
     * @param scanPackage
     * @return
     */
    private static List<TableSortSql> dropTableSqlList(DbType dbType, String scanPackage) {
        List<TableSortSql> sqlList = new LinkedList<>();
        Set<Class<? extends Entity>> classSetAll = ReflectionsUtil.getSubClassSet(Entity.class, scanPackage);
        List<Class<? extends Entity>> entityList = getSortEntityList(classSetAll);
        // 反转list，必须反转，创建顺序与删除顺序正好相反
        Collections.reverse(entityList);
        ITable iTable = TableFactory.getInstance(dbType);
        for (Class<? extends Entity> entityClass : entityList) {
            String sql = iTable.drop(entityClass);
            sqlList.add(new TableSortSql(sql, entityClass));
        }
        return sqlList;
    }

    /**
     * 按顺序删除所有表脚本列表
     *
     * @param dbType
     * @param clazz
     * @return
     */
    private static TableSortSql dropTableSql(DbType dbType, Class<? extends Entity> clazz) {
        ITable iTable = TableFactory.getInstance(dbType);
        String sql = iTable.drop(clazz);
        TableSortSql result = new TableSortSql(sql, clazz);
        return result;
    }

    /**
     * 创建所有表脚本列表
     *
     * @param dbType      数据库类型
     * @param scanPackage
     * @return
     */
    private static List<TableSortSql> createTableSqlList(DbType dbType, String scanPackage) {
        List<TableSortSql> sqlList = new ArrayList<>();
        Set<Class<? extends Entity>> classSetAll = ReflectionsUtil.getSubClassSet(Entity.class, scanPackage);
        List<Class<? extends Entity>> entityList = getSortEntityList(classSetAll);
        ITable iTable = TableFactory.getInstance(dbType);
        for (Class<? extends Entity> entityClass : entityList) {
            String sql = iTable.create(entityClass);
            sqlList.add(new TableSortSql(sql, entityClass));
        }
        return sqlList;
    }

    /**
     * 创建表脚本
     *
     * @param dbType 数据库类型
     * @param clazz  实体类
     * @return
     */
    private static TableSortSql createTableSql(DbType dbType, Class<? extends Entity> clazz) {
        ITable iTable = TableFactory.getInstance(dbType);
        String sql = iTable.create(clazz);
        TableSortSql result = new TableSortSql(sql, clazz);
        return result;
    }

    /**
     * 获取表顺序
     *
     * @param classSetAll
     * @return
     */
    private static List<Class<? extends Entity>> getSortEntityList(Set<Class<? extends Entity>> classSetAll) {
        // 全部排序列表
        List<List<Class<? extends Entity>>> listAll = new LinkedList<>();
        for (Class<? extends Entity> clazz : classSetAll) {
            List<Class<? extends Entity>> listOne = new LinkedList<>();
            listOne.add(clazz);
            getTableSortList(listAll, clazz, listOne);
        }

        List<TableSort> listNodes = new LinkedList<>();
        for (List<Class<? extends Entity>> nodes : listAll) {
            for (int i = 0; i < nodes.size(); i++) {
                TableSort sort = TableSort.builder()
                        .clazz(nodes.get(i))
                        .sort(0 - i)
                        .build();
                listNodes.add(sort);
            }
        }

        List<TableSort> sortList = new LinkedList<>();
        Map<Class<? extends Entity>, List<TableSort>> map = listNodes.stream().collect(Collectors.groupingBy(e -> e.getClazz()));
        for (Map.Entry<Class<? extends Entity>, List<TableSort>> entry : map.entrySet()) {
            List<TableSort> sorts = entry.getValue();
            int min = 100;
            for (TableSort sort : sorts) {
                if (sort.getSort() < min) {
                    min = sort.getSort();
                }
            }
            TableSort sort = TableSort.builder()
                    .clazz(entry.getKey())
                    .sort(min)
                    .build();
            sortList.add(sort);
        }
        //根据排序字段升序排列
        Collections.sort(sortList, (o1, o2) -> o1.getSort() - o2.getSort());
        List<Class<? extends Entity>> entityList = sortList.stream().map(e -> e.getClazz()).collect(Collectors.toList());
        return entityList;
    }

    /**
     * 回溯算法解决遍历获取所有表关联列举
     *
     * @param listAll
     * @param clazz
     * @param listOne
     */
    private static void getTableSortList(List<List<Class<? extends Entity>>> listAll,
                                         Class<? extends Entity> clazz, List<Class<? extends Entity>> listOne) {
        TableInfo tableInfo = TableHelperUtil.getTableInfo(clazz);
        List<TableFkInfo> fkList = tableInfo.getFkList();
        if (fkList.size() == 0) {
            log.debug(listOne.stream().map(e -> e.getSimpleName()).collect(Collectors.joining("->")));
            listAll.add(new LinkedList<>(listOne));
        } else {
            for (TableFkInfo fk : fkList) {
                Class<? extends Entity> fkClass = fk.getPkEntity();
                listOne.add(fkClass);
                getTableSortList(listAll, fkClass, listOne);
                listOne.remove(listOne.size() - 1);
            }
        }
    }
}
